#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.${artifactId};

import ${package}.api.*;

import java.io.BufferedReader;
import java.io.Console;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.PasswordAuthentication;
import com.sun.sgs.${artifactId}.*;
import com.sun.sgs.${artifactId}.simple.SimpleClient;
import com.sun.sgs.${artifactId}.simple.SimpleClientListener;

import java.nio.ByteBuffer;
import java.util.Properties;

public class MyClient
    extends Thread
    implements SimpleClientListener
{
    private static final long serialVersionUID = 1L;
    public static final String DEFAULT_PORT = "1139";
    protected SimpleClient simpleClient;
    protected Console console;

    public static void main(String ... args) throws Exception
    {
        MyClient ${artifactId} = new MyClient();
        ${artifactId}.login();
        ${artifactId}.start();
    }

    public MyClient()
    {
        super("MyClient");
        console = System.console();
        simpleClient = new SimpleClient(this);
    }

    public void run()
    {
        console.format("Now accepting console input. Each line will be sent to the server when you hit 'enter'. Type 'quit' to stop.${symbol_escape}n");
        while(true)
        {
            try {
                if(!console.reader().ready())
                {
                    try{Thread.sleep(200);}catch(InterruptedException ie){}
                    continue;
                }
                
                String line = console.readLine().trim();
                if("exit".equalsIgnoreCase(line) || "quit".equalsIgnoreCase(line))
                    break;

                simpleClient.send(MyApp.encode(line));
            } catch (IOException e) {
                error(e);
            }
        }
        console.format("No longer accepting console input${symbol_escape}n");
    }

    public void login() throws IOException
    {
        Properties connectProps = new Properties();
        connectProps.put("host", "localhost");
        connectProps.put("port", DEFAULT_PORT);
        simpleClient.login(connectProps);
    }

    public PasswordAuthentication getPasswordAuthentication()
    {
        return new PasswordAuthentication("anonymous", "guest".toCharArray());
    }

    public void loggedIn()
    {
        console.format("Logged in!${symbol_escape}n");
    }

    public void loginFailed(String reason)
    {
        console.format("Login failed: %s${symbol_escape}n", reason);
    }

    public ClientChannelListener joinedChannel(ClientChannel ${artifactId}Channel)
    {
        console.format("Joined channel: %s${symbol_escape}n", ${artifactId}Channel.getName());
        return new ClientChannelListener(){
            public void receivedMessage(ClientChannel ${artifactId}Channel, ByteBuffer byteBuffer)
            {
                try {
                    console.format("[%s] %s${symbol_escape}n", ${artifactId}Channel.getName(), MyApp.decode(byteBuffer));
                } catch (UnsupportedEncodingException e) {
                    error(e);
                }
            }

            public void leftChannel(ClientChannel ${artifactId}Channel)
            {
                console.format("Left channel: %s${symbol_escape}n", ${artifactId}Channel.getName());
            }
        };
    }

    public void receivedMessage(ByteBuffer byteBuffer)
    {
        try {
            console.format("[server] %s${symbol_escape}n", MyApp.decode(byteBuffer));
        } catch (UnsupportedEncodingException e) {
            error(e);
        }
    }

    public void reconnecting()
    {
        console.format("reconnecting...${symbol_escape}n");
    }

    public void reconnected()
    {
        console.format("reconnected${symbol_escape}n");
    }

    public void disconnected(boolean graceful, String reason)
    {
        console.format("%s: disconnected${symbol_escape}n", graceful ? "Graceful shutdown" : "Not gracefully shutdown");
    }

    private void error(Throwable t)
    {
        console.format("ERROR: %s${symbol_escape}n", t.getMessage());
        t.printStackTrace(console.writer());
    }
}